# -*- coding: utf-8 -*-
import re

from sc_engine.repositories import Repository

class LeagueStageConversionFailedError(Exception): pass

class LeagueStageConverter(object):
    """Convert from stage aliases to stage paths and back again.

    Using knowledge of a league's stage, can try to convert the stage name (as
    is found on the kespa website) into a stage path by using the
    ``find_stage_path`` method, or get info on a stage path through the
    ``find_stage_data`` method.
    """

    possible_conversions = [
        re.compile(u'(\d+)R 온게임넷 (\d+)주차 (\d+)경기'),
        re.compile(u'(\d+)R 온게임넷 (\d+)차 (\d+)경기'),
        re.compile(u'(\d+)R (\d+)주차 온게임넷 (\d+)경기'),
        re.compile(u'(\d+)R MBC게임 (\d+)주차 (\d+)경기'),
        re.compile(u'(\d+)R MBC (\d+)주차 (\d+)경기'),
        re.compile(u'(\d+)R MBC경기 (\d+)주차 (\d+)경기'),
    ]

    def __init__(self, stage_template, stage_known_dates,
            stage_aliases, stage_exceptions):

        self.template = stage_template
        self.aliases = stage_aliases
        self.known_dates = stage_known_dates

         # Convert the exceptions to a dictionary with the stage_path as a tuple
         # for the key for easy lookups.
        stage_exceptions = [(tuple(k),v) for (k,v) in stage_exceptions]
        self.exceptions = dict(stage_exceptions)

        self.regexes = {}

    def _convert_stage_path_values(self, stage):
        for possible_conversion in self.possible_conversions:
            result = possible_conversion.findall(stage)
            if result:
                return result[0]

        return None

    def find_stage_path(self, stage, date):
        """Find the stage path given kespa's name of the stage on a given date.

        Given the text used to describe the stage, generate the stage path.
        This may need to parse the text for data used to fill a template, to
        use the stage path associated with an alias, or just look up the date in
        a list of known dates.
        """
        if stage in self.aliases:
            return self.aliases[stage]

        if date in self.known_dates:
            return self.known_dates[date]

        stage_path_values = self._convert_stage_path_values(stage)

        if stage_path_values == None:
            err_msg = 'Could not convert stage %s' % stage
            raise LeagueStageConversionFailedError(err_msg)

        stage_path = []

        for stage_template, stage_value in zip(self.template, stage_path_values):
            stage_name_key = stage_template['name_key'] % stage_value
            stage_path.append(stage_name_key)

            stage_part = tuple(stage_path)

            if stage_part in self.exceptions:
                stage_path[-1] = self.exceptions[stage_part]['name_key']

        return stage_path

    def _find_single_stage_data(self, stage_part, template):
        # Try finding it as an exception.
        for exception, exception_data in self.exceptions.items():
            if len(stage_part) == len(exception):
                if exception_data.get('name_key', exception[-1]) == stage_part[-1]:
                    data = exception_data.copy()
                    if 'name_key' in data:
                        del data['name_key']
                    if 'format' not in data:
                        data['format'] = None
                    return data

        # Try to convert the name_key used back to find the original template.
        if tuple(stage_part) in self.exceptions:
            return self.exceptions[tuple(stage_part)]

        template_name_key = template['name_key']

        if template_name_key in self.regexes:
            regexp = self.regexes[template_name_key]
        else:
            regexp = re.compile(template_name_key.replace('%s', '([\d\w]+)'))
            self.regexes[template_name_key] = regexp

        stage_value = regexp.findall(stage_part[-1])
        name = template['name'] % stage_value[0]

        return {
            'name' : name,
            'format' : template.get('format', None)
        }

    def find_stage_data(self, stage_path):
        """
        Using a specific stage path, get the data for all the stages of the
        stage path.
        
        Returns a list for each stage of the stage path, with each stage
        containing a dictoinary with...
            stage_path: The stage path to this stage.
            name: The name of the stage path
            format: The format used (or None)
        """
        results = []
        stage_parts = []

        for name_key, template in zip(stage_path, self.template):
            current_stage_path = stage_parts + [name_key]
            data = self._find_single_stage_data(current_stage_path, template)
            stage_parts.append(name_key)
            data['stage_path'] = stage_parts[:]
            results.append(data)

        return results



            
